/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package persistence;

import entityBeans.Geospatialelement;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import entityBeans.Georeferenceverificationstatus;
import entityBeans.Georeferencesource;
import java.util.ArrayList;
import java.util.List;
import entityBeans.Specimen;
import persistence.exceptions.NonexistentEntityException;

/**
 *
 * @author allankv
 */
public class GeospatialelementJpaController {

    public GeospatialelementJpaController() {
        emf = Persistence.createEntityManagerFactory("bdd-javaPU");
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Geospatialelement geospatialelement) {
        if (geospatialelement.getGeoreferencesourceList() == null) {
            geospatialelement.setGeoreferencesourceList(new ArrayList<Georeferencesource>());
        }
        if (geospatialelement.getSpecimenList() == null) {
            geospatialelement.setSpecimenList(new ArrayList<Specimen>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Georeferenceverificationstatus georeferenceverificationstatus = geospatialelement.getGeoreferenceverificationstatus();
            if (georeferenceverificationstatus != null) {
                georeferenceverificationstatus = em.getReference(georeferenceverificationstatus.getClass(), georeferenceverificationstatus.getIdgeoreferenceverificationstatus());
                geospatialelement.setGeoreferenceverificationstatus(georeferenceverificationstatus);
            }
            List<Georeferencesource> attachedGeoreferencesourceList = new ArrayList<Georeferencesource>();
            for (Georeferencesource georeferencesourceListGeoreferencesourceToAttach : geospatialelement.getGeoreferencesourceList()) {
                georeferencesourceListGeoreferencesourceToAttach = em.getReference(georeferencesourceListGeoreferencesourceToAttach.getClass(), georeferencesourceListGeoreferencesourceToAttach.getIdgeoreferencesource());
                attachedGeoreferencesourceList.add(georeferencesourceListGeoreferencesourceToAttach);
            }
            geospatialelement.setGeoreferencesourceList(attachedGeoreferencesourceList);
            List<Specimen> attachedSpecimenList = new ArrayList<Specimen>();
            for (Specimen specimenListSpecimenToAttach : geospatialelement.getSpecimenList()) {
                specimenListSpecimenToAttach = em.getReference(specimenListSpecimenToAttach.getClass(), specimenListSpecimenToAttach.getIdspecimen());
                attachedSpecimenList.add(specimenListSpecimenToAttach);
            }
            geospatialelement.setSpecimenList(attachedSpecimenList);
            em.persist(geospatialelement);
            if (georeferenceverificationstatus != null) {
                georeferenceverificationstatus.getGeospatialelementList().add(geospatialelement);
                georeferenceverificationstatus = em.merge(georeferenceverificationstatus);
            }
            for (Georeferencesource georeferencesourceListGeoreferencesource : geospatialelement.getGeoreferencesourceList()) {
                georeferencesourceListGeoreferencesource.getGeospatialelementList().add(geospatialelement);
                georeferencesourceListGeoreferencesource = em.merge(georeferencesourceListGeoreferencesource);
            }
            for (Specimen specimenListSpecimen : geospatialelement.getSpecimenList()) {
                Geospatialelement oldGeospatialelementOfSpecimenListSpecimen = specimenListSpecimen.getGeospatialelement();
                specimenListSpecimen.setGeospatialelement(geospatialelement);
                specimenListSpecimen = em.merge(specimenListSpecimen);
                if (oldGeospatialelementOfSpecimenListSpecimen != null) {
                    oldGeospatialelementOfSpecimenListSpecimen.getSpecimenList().remove(specimenListSpecimen);
                    oldGeospatialelementOfSpecimenListSpecimen = em.merge(oldGeospatialelementOfSpecimenListSpecimen);
                }
            }
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Geospatialelement geospatialelement) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Geospatialelement persistentGeospatialelement = em.find(Geospatialelement.class, geospatialelement.getIdgeospatialelement());
            Georeferenceverificationstatus georeferenceverificationstatusOld = persistentGeospatialelement.getGeoreferenceverificationstatus();
            Georeferenceverificationstatus georeferenceverificationstatusNew = geospatialelement.getGeoreferenceverificationstatus();
            List<Georeferencesource> georeferencesourceListOld = new ArrayList<Georeferencesource>(); //persistentGeospatialelement.getGeoreferencesourceList();
            List<Georeferencesource> georeferencesourceListNew = new ArrayList<Georeferencesource>(); //geospatialelement.getGeoreferencesourceList();
            List<Specimen> specimenListOld = new ArrayList<Specimen>(); //persistentGeospatialelement.getSpecimenList();
            List<Specimen> specimenListNew = new ArrayList<Specimen>(); //geospatialelement.getSpecimenList();
            if (georeferenceverificationstatusNew != null) {
                georeferenceverificationstatusNew = em.getReference(georeferenceverificationstatusNew.getClass(), georeferenceverificationstatusNew.getIdgeoreferenceverificationstatus());
                geospatialelement.setGeoreferenceverificationstatus(georeferenceverificationstatusNew);
            }
            List<Georeferencesource> attachedGeoreferencesourceListNew = new ArrayList<Georeferencesource>();
            for (Georeferencesource georeferencesourceListNewGeoreferencesourceToAttach : georeferencesourceListNew) {
                georeferencesourceListNewGeoreferencesourceToAttach = em.getReference(georeferencesourceListNewGeoreferencesourceToAttach.getClass(), georeferencesourceListNewGeoreferencesourceToAttach.getIdgeoreferencesource());
                attachedGeoreferencesourceListNew.add(georeferencesourceListNewGeoreferencesourceToAttach);
            }
            georeferencesourceListNew = attachedGeoreferencesourceListNew;
            geospatialelement.setGeoreferencesourceList(georeferencesourceListNew);
            List<Specimen> attachedSpecimenListNew = new ArrayList<Specimen>();
            for (Specimen specimenListNewSpecimenToAttach : specimenListNew) {
                specimenListNewSpecimenToAttach = em.getReference(specimenListNewSpecimenToAttach.getClass(), specimenListNewSpecimenToAttach.getIdspecimen());
                attachedSpecimenListNew.add(specimenListNewSpecimenToAttach);
            }
            specimenListNew = attachedSpecimenListNew;
            geospatialelement.setSpecimenList(specimenListNew);
            geospatialelement = em.merge(geospatialelement);
            if (georeferenceverificationstatusOld != null && !georeferenceverificationstatusOld.equals(georeferenceverificationstatusNew)) {
                georeferenceverificationstatusOld.getGeospatialelementList().remove(geospatialelement);
                georeferenceverificationstatusOld = em.merge(georeferenceverificationstatusOld);
            }
            if (georeferenceverificationstatusNew != null && !georeferenceverificationstatusNew.equals(georeferenceverificationstatusOld)) {
                georeferenceverificationstatusNew.getGeospatialelementList().add(geospatialelement);
                georeferenceverificationstatusNew = em.merge(georeferenceverificationstatusNew);
            }
            for (Georeferencesource georeferencesourceListOldGeoreferencesource : georeferencesourceListOld) {
                if (!georeferencesourceListNew.contains(georeferencesourceListOldGeoreferencesource)) {
                    georeferencesourceListOldGeoreferencesource.getGeospatialelementList().remove(geospatialelement);
                    georeferencesourceListOldGeoreferencesource = em.merge(georeferencesourceListOldGeoreferencesource);
                }
            }
            for (Georeferencesource georeferencesourceListNewGeoreferencesource : georeferencesourceListNew) {
                if (!georeferencesourceListOld.contains(georeferencesourceListNewGeoreferencesource)) {
                    georeferencesourceListNewGeoreferencesource.getGeospatialelementList().add(geospatialelement);
                    georeferencesourceListNewGeoreferencesource = em.merge(georeferencesourceListNewGeoreferencesource);
                }
            }
            for (Specimen specimenListOldSpecimen : specimenListOld) {
                if (!specimenListNew.contains(specimenListOldSpecimen)) {
                    specimenListOldSpecimen.setGeospatialelement(null);
                    specimenListOldSpecimen = em.merge(specimenListOldSpecimen);
                }
            }
            for (Specimen specimenListNewSpecimen : specimenListNew) {
                if (!specimenListOld.contains(specimenListNewSpecimen)) {
                    Geospatialelement oldGeospatialelementOfSpecimenListNewSpecimen = specimenListNewSpecimen.getGeospatialelement();
                    specimenListNewSpecimen.setGeospatialelement(geospatialelement);
                    specimenListNewSpecimen = em.merge(specimenListNewSpecimen);
                    if (oldGeospatialelementOfSpecimenListNewSpecimen != null && !oldGeospatialelementOfSpecimenListNewSpecimen.equals(geospatialelement)) {
                        oldGeospatialelementOfSpecimenListNewSpecimen.getSpecimenList().remove(specimenListNewSpecimen);
                        oldGeospatialelementOfSpecimenListNewSpecimen = em.merge(oldGeospatialelementOfSpecimenListNewSpecimen);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = geospatialelement.getIdgeospatialelement();
                if (findGeospatialelement(id) == null) {
                    throw new NonexistentEntityException("The geospatialelement with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Geospatialelement geospatialelement;
            try {
                geospatialelement = em.getReference(Geospatialelement.class, id);
                geospatialelement.getIdgeospatialelement();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The geospatialelement with id " + id + " no longer exists.", enfe);
            }
            Georeferenceverificationstatus georeferenceverificationstatus = geospatialelement.getGeoreferenceverificationstatus();
            if (georeferenceverificationstatus != null) {
                georeferenceverificationstatus.getGeospatialelementList().remove(geospatialelement);
                georeferenceverificationstatus = em.merge(georeferenceverificationstatus);
            }
            List<Georeferencesource> georeferencesourceList = geospatialelement.getGeoreferencesourceList();
            for (Georeferencesource georeferencesourceListGeoreferencesource : georeferencesourceList) {
                georeferencesourceListGeoreferencesource.getGeospatialelementList().remove(geospatialelement);
                georeferencesourceListGeoreferencesource = em.merge(georeferencesourceListGeoreferencesource);
            }
            List<Specimen> specimenList = geospatialelement.getSpecimenList();
            for (Specimen specimenListSpecimen : specimenList) {
                specimenListSpecimen.setGeospatialelement(null);
                specimenListSpecimen = em.merge(specimenListSpecimen);
            }
            em.remove(geospatialelement);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Geospatialelement> findGeospatialelementEntities() {
        return findGeospatialelementEntities(true, -1, -1);
    }

    public List<Geospatialelement> findGeospatialelementEntities(int maxResults, int firstResult) {
        return findGeospatialelementEntities(false, maxResults, firstResult);
    }

    private List<Geospatialelement> findGeospatialelementEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Geospatialelement.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Geospatialelement findGeospatialelement(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Geospatialelement.class, id);
        } finally {
            em.close();
        }
    }

    public int getGeospatialelementCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Geospatialelement> rt = cq.from(Geospatialelement.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

}
